#include <stdbool.h>
#include <string.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <netdb.h>
#include <string.h>
#include <sys/un.h> 
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <netinet/in.h> 
#include <arpa/inet.h>
#include <unistd.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <ctype.h>
#include <pthread.h>
#include <semaphore.h>

#include "constantes.h"
#include "estructuras.h"
#include "sockets.h"
#include "NIPC.h"
#include "recibirComando.h"

extern int posicionCabezal;
extern int ALG;
extern float RPM;
extern chs glChs;
extern char * algoritmo;
extern pthread_mutex_t mutex;  


int recibircomando (void *args) {
	
	int tam;
	int comando;
	char *parametro;
	int i;
	int tamanio;
	struct sockaddr_un local,remote;
	int len,t;
	int count;
	pid_t child;
	int escucha_consola;
	char sAux[10];
	char sPosicionCabezal[10];
	char sSocket[20];
	int sectorInicial;
	int sectorFinal;
	int aux;
	
	printf("ALG %i\n",ALG);
	
	colas2 *q = (colas2 *) args;
   
	if ((escucha_consola = socket(AF_UNIX, SOCK_STREAM, 0)) == -1) {
        printf("error al crear socket\n\n");
        exit(EXIT_FAILURE);
	}

	local.sun_family = AF_UNIX;
	strcpy(local.sun_path,"sock_consola");
	unlink(local.sun_path);
		
    len = strlen(local.sun_path) + sizeof(local.sun_family);
    if (bind(escucha_consola, (struct sockaddr *)&local, len) == -1) {
        perror("bind");
		exit(EXIT_FAILURE);
    }
	
    if (listen(escucha_consola, 5) == -1) {
        perror("listen");
		exit(EXIT_FAILURE);
    }
	
   if((child=fork())==-1){
		perror("fork");
		exit(EXIT_FAILURE);    
    }
    else if (child==0){
		execv("./consola",NULL);	
    }
	
	t = sizeof(remote);
	if ((Sock_consola = accept(escucha_consola, (struct sockaddr *)&remote, &t)) == -1) {
			perror("accept");
			exit(EXIT_FAILURE);
	}
	
	InfoIPC rInfoIPC60;
	intacad(ALG,sAux);
	rInfoIPC60.payLoadLength= strlen(sAux) + 1;	
	generarStructIPC(sAux,ALGORITMO,&rInfoIPC60);
	printf("rInfoIPC60 %s \n",rInfoIPC60.payload);
	enviarIPC(Sock_consola,&rInfoIPC60);
	free(rInfoIPC60.payload);
	
	
	while(1)
	{
		
		InfoIPC infoIPC;	
		if(recibirIPC(Sock_consola,&infoIPC)<0){	
			printf("Se cayo CONSOLA \n");
			close(Sock_consola);
			break;
		}
		
		
		if((infoIPC.payLoadDescriptor==INFO_REQUEST))
		{	
			/*Le envio a la consola la posicion del cabezal*/
			InfoIPC rInfoIPC50;
			intacad(posicionCabezal,sPosicionCabezal);
			rInfoIPC50.payLoadLength= strlen(sPosicionCabezal) + 1;	
			generarStructIPC(sPosicionCabezal,POSICION_CABEZAL,&rInfoIPC50);
			enviarIPC(Sock_consola,&rInfoIPC50);
			free(rInfoIPC50.payload);
		}
		
		if((infoIPC.payLoadDescriptor==TAMANIO_TRACE))
		{
			for(i=0;i<5;i++)
				VectorTrace[i]=-1;
		
			tamanio=atoi(infoIPC.payload);
		}
		
		if((infoIPC.payLoadDescriptor==START_TRACE))
		{	
			
			/*Le envio a la consola la posicion del cabezal*/
			InfoIPC rInfoIPC38;
			intacad(posicionCabezal,sPosicionCabezal);
			rInfoIPC38.payLoadLength= strlen(sPosicionCabezal) + 1;	
			generarStructIPC(sPosicionCabezal,START_TRACE,&rInfoIPC38);
			enviarIPC(Sock_consola,&rInfoIPC38);
			free(rInfoIPC38.payload);
			
			count=0;
			while(count<tamanio)
			{
				InfoIPC infoIPC2;
				recibirIPC(Sock_consola, &infoIPC2);
				VectorTrace[count]=atoi(infoIPC2.payload);
				count++;
				free(infoIPC2.payload);
			
			}
			
			count=0;
			while(count<tamanio)
			{
				
				struct ListaIDdescriptors * NodoDescriptores = (struct ListaIDdescriptors *)malloc(sizeof(struct ListaIDdescriptors));	
				strcpy(NodoDescriptores->sDescriptorID_delPedido,"-2");
				NodoDescriptores->sector=VectorTrace[count];
				intacad(Sock_consola,sSocket);
				strcpy(NodoDescriptores->sSocketPorElCualResponder,sSocket);
				NodoDescriptores->Sgt = NULL;
				NodoDescriptores->Ant = NULL;        
				strcpy(NodoDescriptores->data,"");
				NodoDescriptores->operacion=4;
				
				if(pthread_mutex_lock(&mutex)!=0){
					perror("pthread_mutex_lock");
					exit(EXIT_FAILURE);
				}
			
				
				AgregarAColaDePedidosADisco(&NodoDescriptores, &q->activacabeza, &q->activacola);
				sem_post(&pedidos);
				
				if(pthread_mutex_unlock(&mutex)!=0){
					perror("pthread_mutex_lock");
					exit(EXIT_FAILURE);
				}
			
				count++;
			}		
			
		}
		
		
		if((infoIPC.payLoadDescriptor==START_CLEAN))
		{	
			
			char* data_sector=(char *)malloc(512);
			memset(data_sector,'0',512); 
			
			InfoIPC infoIPC4;
			recibirIPC(Sock_consola, &infoIPC4);
			sectorInicial=atoi(infoIPC4.payload);
			free(infoIPC4.payload);
			
			InfoIPC infoIPC5;
			recibirIPC(Sock_consola, &infoIPC5);
			sectorFinal=atoi(infoIPC5.payload);
			free(infoIPC5.payload);
			
			aux=sectorInicial;
	
	
			while(aux!=sectorFinal){
				
				aux++;
				
				struct ListaIDdescriptors * NodoDescriptores = (struct ListaIDdescriptors *)malloc(sizeof(struct ListaIDdescriptors));	
				strcpy(NodoDescriptores->sDescriptorID_delPedido,"-3");
				NodoDescriptores->sector=aux;
				intacad(Sock_consola,sSocket);
				strcpy(NodoDescriptores->sSocketPorElCualResponder,sSocket);
				NodoDescriptores->Sgt = NULL;
				NodoDescriptores->Ant = NULL;        
				memcpy(NodoDescriptores->data,data_sector,512);
				NodoDescriptores->operacion=5;
				
				if(pthread_mutex_lock(&mutex)!=0){
					perror("pthread_mutex_lock");
					exit(EXIT_FAILURE);
				}
			
				
				AgregarAColaDePedidosADisco(&NodoDescriptores, &q->activacabeza, &q->activacola);
				sem_post(&pedidos);
				
				if(pthread_mutex_unlock(&mutex)!=0){
					perror("pthread_mutex_lock");
					exit(EXIT_FAILURE);
				}
				
			}
		
			free(data_sector);
		}
		
		free(infoIPC.payload);
	}

}


 
int dentroDeRango(int unSector, int sectores_totales_vda)
{ 
	int resultado=0;
	sectores_totales_vda--;
	if(unSector <= sectores_totales_vda && unSector >= 0)
	{
		resultado = 1;
	}

	return resultado;
}		

int esnum(char letra){
      
     if((isdigit(letra))) 
      return 0;
     
     return 1;   
}


